Type system - Wikipedia#Static_type_checking

Static type checking

Static type checking is the process of verifying the type safety of a program based on analysis of a program’s text (source code). If a program passes a static type checker, then the program is guaranteed to satisfy some set of type safety properties for all possible inputs.

Static type checking can be considered a limited form of program verification (see type safety), and in a type-safe language, can also be considered an optimization. If a compiler can prove that a program is well-typed, then it does not need to emit dynamic safety checks, allowing the resulting compiled binary to run faster and to be smaller.

Static type checking for Turing-complete languages is inherently conservative. That is, if a type system is both sound (meaning that it rejects all incorrect programs) and decidable (meaning that it is possible to write an algorithm that determines whether a program is well-typed), then it must be incomplete (meaning there are correct programs, which are also rejected, even though they do not encounter runtime errors).1 For example, consider a program containing the code:

  • ✤ if <complex test> then <do something> else <signal that there is a type error>

Even if the expression <complex test> always evaluates to true at runtime, most type checkers will reject the program as ill-typed, because it is difficult (if not impossible) for a static analyzer to determine that the else branch will not be taken.2 Consequently, a static type checker will quickly detect type errors in rarely used code paths. Without static type checking, even code coverage tests with 100% coverage may be unable to find such type errors. The tests may fail to detect such type errors, because the combination of all places where values are created and all places where a certain value is used must be taken into account.

A number of useful and common programming language features cannot be checked statically, such as downcasting. Thus, many languages will have both static and dynamic type checking; the static type checker verifies what it can, and dynamic checks verify the rest.

Many languages with static type checking provide a way to bypass the type checker. Some languages allow programmers to choose between static and dynamic type safety. For example, historically C# declares variables statically,3 but C# 4.0 introduces the dynamic keyword, which is used to declare variables to be checked dynamically at runtime.3 Other languages allow writing code that is not type-safe; for example, in C, programmers can freely cast a value between any two types that have the same size, effectively subverting the type concept.

Printed 2026-10-25.

(echo:: @ ᯤ)

Footnotes

  1. ”… any sound, decidable type system must be incomplete” —D. Remy (2017). p. 29, Remy, Didier. “Type systems for programming languages” (PDF). Archived from the original (PDF) on 14 November 2017. Retrieved 26 May 2013. ↩

  2. Pierce 2002. ↩

  3. Skeet, Jon (2019). C# in Depth (4 ed.). Manning. ISBN 978-1617294532. ↩ ↩2